RColorBrewer

How to expand color palette with ggplot and RColorBrewer

https://www.r-bloggers.com/how-to-expand-color-palette-with-ggplot-and-rcolorbrewer/

highcharter

http://jkunst.com/highcharter/

https://github.com/jbkunst/highcharter

http://www.htmlwidgets.org/index.html

https://cran.r-project.org/web/packages/highcharter/index.html

https://www.datacamp.com/community/tutorials/data-visualization-highcharter-r

library(tidyverse)
library(highcharter)
glimpse(pokemon)
Observations: 718
Variables: 20
$ id              <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 1...
$ pokemon         <chr> "bulbasaur", "ivysaur", "ven...
$ species_id      <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 1...
$ height          <int> 7, 10, 20, 6, 11, 17, 5, 10,...
$ weight          <int> 69, 130, 1000, 85, 190, 905,...
$ base_experience <int> 64, 142, 236, 62, 142, 240, ...
$ type_1          <chr> "grass", "grass", "grass", "...
$ type_2          <chr> "poison", "poison", "poison"...
$ attack          <int> 49, 62, 82, 52, 64, 84, 48, ...
$ defense         <int> 49, 63, 83, 43, 58, 78, 65, ...
$ hp              <int> 45, 60, 80, 39, 58, 78, 44, ...
$ special_attack  <int> 65, 80, 100, 60, 80, 109, 50...
$ special_defense <int> 65, 80, 100, 50, 65, 85, 64,...
$ speed           <int> 45, 60, 80, 65, 80, 100, 43,...
$ color_1         <chr> "#78C850", "#78C850", "#78C8...
$ color_2         <chr> "#A040A0", "#A040A0", "#A040...
$ color_f         <chr> "#81A763", "#81A763", "#81A7...
$ egg_group_1     <chr> "monster", "monster", "monst...
$ egg_group_2     <chr> "plant", "plant", "plant", "...
$ url_image       <chr> "1.png", "2.png", "3.png", "...
hchart works like ggplot2's qplot.
hc_add_series works like ggplot2's geom_S.
hcaes works like ggplot2's aes.
pokemon %>%
  count(type_1) %>%
  arrange(n) %>%
  hchart(type = "bar", hcaes(x = "type_1", y = "n"))
pokemon %>%
  count(type_1) %>%
  arrange(n) %>%
  hchart(type = "column", hcaes(x = "type_1", y = "n"))
pokemon %>%
  count(type_1) %>%
  arrange(n) %>%
  hchart(type = "treemap", hcaes(x = "type_1", value = "n", color = "n"))
highchart() %>%
  hc_add_series(pokemon, "scatter", hcaes(x = "height", y = "weight"))
highchart() %>%
  hc_chart(type = "area") %>%
  hc_title(text = "Historic and Estimated Worldwide Population Distribution by Region") %>%
  hc_subtitle(text = "Source: Wikipedia.org") %>%
  hc_xAxis(categories = c("1750", "1800", "1850", "1900", "1950", "1999", "2050"),
           tickmarkPlacement = "on",
           title = list(enabled = FALSE)) %>%
  hc_yAxis(title = list(text = "Percent")) %>%
  hc_tooltip(pointFormat = "<span style=\"color:{series.color}\">{series.name}</span>:
             <b>{point.percentage:.1f}%</b> ({point.y:,.0f} millions)<br/>",
             shared = TRUE) %>%
  hc_plotOptions(area = list(
     stacking = "percent",
     lineColor = "#ffffff",
     lineWidth = 1,
     marker = list(
       lineWidth = 1,
       lineColor = "#ffffff"
       ))
     ) %>%
  hc_add_series(name = "Asia", data = c(502, 635, 809, 947, 1402, 3634, 5268)) %>%
  hc_add_series(name = "Africa", data = c(106, 107, 111, 133, 221, 767, 1766)) %>%
  hc_add_series(name = "Europe", data = c(163, 203, 276, 408, 547, 729, 628)) %>%
  hc_add_series(name = "America", data = c(18, 31, 54, 156, 339, 818, 1201)) %>%
  hc_add_series(name = "Oceania", data = c(2, 2, 2, 6, 13, 30, 46))
y <- quantmod::getSymbols("AMZN", auto.assign = FALSE)

highchart(type = "stock") %>%
  hc_add_series(x) %>%
  hc_add_series(y, type = "ohlc")

Highmaps - Map Collection
https://code.highcharts.com/mapdata/

hcmap("https://code.highcharts.com/mapdata/countries/in/in-all.js")%>%
  hc_title(text = "India")
trying URL 'https://code.highcharts.com/mapdata/countries/in/in-all.js'
Content type 'application/x-javascript' length 52341 bytes (51 KB)
==================================================
downloaded 51 KB
hcmap("https://code.highcharts.com/mapdata/countries/tr/tr-all.js")%>%
  hc_title(text = "Turkey")
trying URL 'https://code.highcharts.com/mapdata/countries/tr/tr-all.js'
Content type 'application/x-javascript' length 80597 bytes (78 KB)
==================================================
downloaded 78 KB
download_map_data: Download the geojson data from the highcharts collection.
get_data_from_map: Get the properties for each region in the map, as the keys from the map data.
glimpse(mapdata)
Observations: 34
Variables: 20
$ `hc-group`    <chr> "admin1", "admin1", "admin1", "admin1", "admin1", "admin1", "admin1", "admin1", "admin1", "admin1"...
$ `hc-middle-x` <dbl> 0.65, 0.59, 0.50, 0.56, 0.46, 0.46, 0.51, 0.59, 0.47, 0.56, 0.60, 0.63, 0.51, 0.53, 0.53, 0.51, 0....
$ `hc-middle-y` <dbl> 0.81, 0.63, 0.74, 0.38, 0.64, 0.51, 0.34, 0.41, 0.60, 0.32, 0.47, 0.55, 0.48, 0.38, 0.39, 0.46, 0....
$ `hc-key`      <chr> "in-py", "in-ld", "in-wb", "in-or", "in-br", "in-sk", "in-ct", "in-tn", "in-mp", "in-2984", "in-ga...
$ `hc-a2`       <chr> "PY", "LD", "WB", "OR", "BR", "SK", "CT", "TN", "MP", "GU", "GA", "NL", "MN", "AR", "MZ", "TR", "D...
$ labelrank     <chr> "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "9", "2", "9"...
$ hasc          <chr> "IN.PY", "IN.LD", "IN.WB", "IN.OR", "IN.BR", "IN.SK", "IN.CT", "IN.", "IN.MP", "IN.", "IN.GA", "IN...
$ `alt-name`    <chr> "Pondicherry|Puduchcheri|Pondichéry", "Íles Laquedives|Laccadive|Minicoy and Amindivi Islands|Lacc...
$ `woe-id`      <chr> "20070459", "2345748", "2345761", "2345755", "2345742", "2345762", "20070464", "2345758", "2345749...
$ fips          <chr> "IN22", "IN14", "IN28", "IN21", "IN34", "IN29", "IN37", "IN22", "IN35", "IN32", "IN08", "IN20", "I...
$ `postal-code` <chr> "PY", "LD", "WB", "OR", "BR", "SK", "CT", "TN", "MP", NA, "GA", "NL", "MN", "AR", "MZ", "TR", NA, ...
$ name          <chr> "Puducherry", "Lakshadweep", "West Bengal", "Orissa", "Bihar", "Sikkim", "Chhattisgarh", "Tamil Na...
$ country       <chr> "India", "India", "India", "India", "India", "India", "India", "India", "India", "India", "India",...
$ `type-en`     <chr> "Union Territory", "Union Territory", "State", "State", "State", "State", "State", "State", "State...
$ region        <chr> "South", "South", "East", "East", "East", "East", "Central", "South", "Central", "West", "West", "...
$ longitude     <chr> "79.7758", "72.7811", "87.7289", "84.4341", "85.8134", "88.4482", "82.3069", "78.2704", "78.421400...
$ `woe-name`    <chr> "Puducherry", "Lakshadweep", "West Bengal", "Orissa", "Bihar", "Sikkim", "Chhattisgarh", "Tamil Na...
$ latitude      <chr> "10.9224", "11.2249", "23.0523", "20.625", "25.6853", "27.5709", "21.8044", "11.0159", "22.9404", ...
$ `woe-label`   <chr> "Puducherry, IN, India", "Lakshadweep, IN, India", "West Bengal, IN, India", "Orissa, IN, India", ...
$ type          <chr> "Union Territor", "Union Territor", "State", "State", "State", "State", "State", "State", "State",...
hcmap("https://code.highcharts.com/mapdata/countries/in/in-all.js", data = State_pop, value = "Population",
      joinBy = c("hc-a2", "State"), name = "Fake data",
      dataLabels = list(enabled = TRUE, format = '{point.name}'),
      borderColor = "#FAFAFA", borderWidth = 0.1,
      tooltip = list(valueDecimals = 0))
trying URL 'https://code.highcharts.com/mapdata/countries/in/in-all.js'
Content type 'application/x-javascript' length 52341 bytes (51 KB)
==================================================
downloaded 51 KB
df <- data_frame(
  name = c("Animals", "Fruits", "Cars"),
  y = c(5, 2, 4),
  drilldown = tolower(name)
)


ds <- list_parse(df)
names(ds) <- NULL


hc <- highchart() %>%
  hc_chart(type = "column") %>%
  hc_title(text = "Basic drilldown") %>%
  hc_xAxis(type = "category") %>%
  hc_legend(enabled = FALSE) %>%
  hc_plotOptions(
    series = list(
      boderWidth = 0,
      dataLabels = list(enabled = TRUE)
    )
  ) %>%
  hc_add_series(
    name = "Things",
    colorByPoint = TRUE,
    data = ds
  )

dfan <- data_frame(
  name = c("Cats", "Dogs", "Cows", "Sheep", "Pigs"),
  value = c(4, 3, 1, 2, 1)
)

dffru <- data_frame(
  name = c("Apple", "Organes"),
  value = c(4, 2)
)

dfcar <- data_frame(
  name = c("Toyota", "Opel", "Volkswage"),
  value = c(4, 2, 2)
)

second_el_to_numeric <- function(ls){

  map(ls, function(x){
    x[[2]] <- as.numeric(x[[2]])
    x
  })

}

dsan <- second_el_to_numeric(list_parse2(dfan))

dsfru <- second_el_to_numeric(list_parse2(dffru))

dscar <- second_el_to_numeric(list_parse2(dfcar))

hc %>%
  hc_drilldown(
    allowPointDrilldown = TRUE,
    series = list(
      list(
        id = "animals",
        data = dsan
      ),
      list(
        id = "fruits",
        data = dsfru
      ),
      list(
        id = "cars",
        data = dscar
      )
    )
  )

NA
tm <- pokemon %>%
  mutate(type_2 = ifelse(is.na(type_2), paste("only", type_1), type_2),
         type_1 = type_1) %>%
  group_by(type_1, type_2) %>%
  summarise(n = n()) %>%
  ungroup() %>%
  treemap::treemap(index = c("type_1", "type_2"),
                   vSize = "n", vColor = "type_1")


tm$tm <- tm$tm %>%
  tbl_df() %>%
  left_join(pokemon %>% select(type_1, type_2, color_f) %>% distinct(), by = c("type_1", "type_2")) %>%
  left_join(pokemon %>% select(type_1, color_1) %>% distinct(), by = c("type_1")) %>%
  mutate(type_1 = paste0("Main ", type_1),
         color = ifelse(is.na(color_f), color_1, color_f))
Column `type_1` joining factor and character vector, coercing into character vectorColumn `type_2` joining factor and character vector, coercing into character vector
highchart() %>%
  hc_add_series_treemap(tm, allowDrillToNode = TRUE,
                        layoutAlgorithm = "squarified")
'hc_add_series_treemap' is deprecated.
Use 'hctreemap' instead.
See help("Deprecated")
pokemon%>%
  count(type_1)%>%
  arrange(n)%>%
  hchart(type = "bar", hcaes(x = "type_1", y = "n", color = "type_1"))%>%
  hc_exporting(enabled = TRUE)
pokemon%>%
  count(type_1)%>%
  arrange(n)%>%
  hchart(type = "bar", hcaes(x = "type_1", y = "n", color = "type_1"))%>%
  hc_exporting(enabled = TRUE)%>%
hc_add_theme(hc_theme_chalk())
data("weather")

x <- c("Min", "Mean", "Max")
y <- sprintf("{point.%s}", c("min_temperaturec", "mean_temperaturec", "max_temperaturec"))
tltip <- tooltip_table(x, y)

hchart(weather, type = "columnrange",
       hcaes(x = "date", low = "min_temperaturec", high = "max_temperaturec",
             color = "mean_temperaturec")) %>%
  hc_chart(polar = TRUE) %>%
  hc_yAxis( max = 30, min = -10, labels = list(format = "{value} C"),
            showFirstLabel = FALSE) %>%
  hc_xAxis(
    title = list(text = ""), gridLineWidth = 0.5,
    labels = list(format = "{value: %b}")) %>%
  hc_tooltip(useHTML = TRUE, pointFormat = tltip,
             headerFormat = as.character(tags$small("{point.x:%d %B, %Y}")))

NA

taucharts

https://www.infoworld.com/video/87337/r-tip-how-to-create-easy-interactive-scatter-plots-with-taucharts



devtools::install_github("hrbrmstr/taucharts")
# githubinstall::githubinstall("taucharts")
library(taucharts)
Error in library(taucharts) : there is no package called ‘taucharts’
mtcars2 <- mtcars %>% 
  select(wt, mpg) %>% 
  mutate(model = row.names(mtcars))
taucharts::tauchart(mtcars2) %>% 
  tau_point(x = "wt", y = "mpg") %>% 
  tau_tooltip() %>% 
  tau_trendline()

gganimate

https://www.infoworld.com/video/89987/r-tip-animations-in-r

ggplot2

http://r-statistics.co/ggplot2-Tutorial-With-R.html

ggplot(diamonds, aes(x=carat))  # if only X-axis is known. The Y-axis can be specified in respective geoms.

ggplot(diamonds, aes(x=carat, y=price))  # if both X and Y axes are fixed for all layers.

ggplot(diamonds, aes(x=carat, color=cut))  # Each category of the 'cut' variable will now have a distinct  color, once a geom is added.

ggplot(diamonds, aes(x=carat), color="steelblue")

ggplot(diamonds, aes(x=carat, y=price, color=cut)) + 
  geom_point() + 
  geom_smooth()

# Adding scatterplot geom (layer1) and smoothing geom (layer2).
ggplot(diamonds) + 
  geom_point(aes(x=carat, y=price, color=cut)) + 
  geom_smooth(aes(x=carat, y=price, color=cut))

# Same as above but specifying the aesthetics inside the geoms.
library(ggplot2)
ggplot(diamonds) + 
  geom_point(aes(x=carat, y=price, color=cut)) + 
  geom_smooth(aes(x=carat, y=price)) # Remove color from geom_smooth

ggplot(diamonds, aes(x=carat, y=price)) + 
  geom_point(aes(color=cut)) + 
  geom_smooth()  # same but simpler

continue from here http://r-statistics.co/ggplot2-Tutorial-With-R.html

LS0tCnRpdGxlOiAiR3JhcGhzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKIyBSQ29sb3JCcmV3ZXIKCkhvdyB0byBleHBhbmQgY29sb3IgcGFsZXR0ZSB3aXRoIGdncGxvdCBhbmQgUkNvbG9yQnJld2VyCgpodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9ob3ctdG8tZXhwYW5kLWNvbG9yLXBhbGV0dGUtd2l0aC1nZ3Bsb3QtYW5kLXJjb2xvcmJyZXdlci8KCgoKIyBoaWdoY2hhcnRlcgoKaHR0cDovL2prdW5zdC5jb20vaGlnaGNoYXJ0ZXIvCgpodHRwczovL2dpdGh1Yi5jb20vamJrdW5zdC9oaWdoY2hhcnRlcgoKaHR0cDovL3d3dy5odG1sd2lkZ2V0cy5vcmcvaW5kZXguaHRtbAoKaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2hpZ2hjaGFydGVyL2luZGV4Lmh0bWwKCmh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb21tdW5pdHkvdHV0b3JpYWxzL2RhdGEtdmlzdWFsaXphdGlvbi1oaWdoY2hhcnRlci1yCgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhpZ2hjaGFydGVyKQoKYGBgCgpgYGB7cn0KZGF0YSgicG9rZW1vbiIpCmdsaW1wc2UocG9rZW1vbikKYGBgCgoKCgoKCmBgYApoY2hhcnQgd29ya3MgbGlrZSBnZ3Bsb3QyJ3MgcXBsb3QuCmhjX2FkZF9zZXJpZXMgd29ya3MgbGlrZSBnZ3Bsb3QyJ3MgZ2VvbV9TLgpoY2FlcyB3b3JrcyBsaWtlIGdncGxvdDIncyBhZXMuCmBgYAoKCgoKCmBgYHtyfQpwb2tlbW9uICU+JQogIGNvdW50KHR5cGVfMSkgJT4lCiAgYXJyYW5nZShuKSAlPiUKICBoY2hhcnQodHlwZSA9ICJiYXIiLCBoY2Flcyh4ID0gInR5cGVfMSIsIHkgPSAibiIpKQpgYGAKCgpgYGB7cn0KcG9rZW1vbiAlPiUKICBjb3VudCh0eXBlXzEpICU+JQogIGFycmFuZ2UobikgJT4lCiAgaGNoYXJ0KHR5cGUgPSAiY29sdW1uIiwgaGNhZXMoeCA9ICJ0eXBlXzEiLCB5ID0gIm4iKSkKYGBgCgoKCmBgYHtyfQpwb2tlbW9uICU+JQogIGNvdW50KHR5cGVfMSkgJT4lCiAgYXJyYW5nZShuKSAlPiUKICBoY2hhcnQodHlwZSA9ICJ0cmVlbWFwIiwgaGNhZXMoeCA9ICJ0eXBlXzEiLCB2YWx1ZSA9ICJuIiwgY29sb3IgPSAibiIpKQpgYGAKCgpgYGB7cn0KaGlnaGNoYXJ0KCkgJT4lCiAgaGNfYWRkX3Nlcmllcyhwb2tlbW9uLCAic2NhdHRlciIsIGhjYWVzKHggPSAiaGVpZ2h0IiwgeSA9ICJ3ZWlnaHQiKSkKYGBgCgoKCgpgYGB7cn0KZGF0YShkaWFtb25kcywgcGFja2FnZSA9ICJnZ3Bsb3QyIikKCnNldC5zZWVkKDEyMykKZGF0YSA8LSBzYW1wbGVfbihkaWFtb25kcywgMzAwKQoKbW9kbHNzIDwtIGxvZXNzKHByaWNlIH4gY2FyYXQsIGRhdGEgPSBkYXRhKQpmaXQgPC0gYXJyYW5nZShicm9vbTo6YXVnbWVudChtb2Rsc3MpLCBjYXJhdCkKCmhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXMoZGF0YSwgdHlwZSA9ICJzY2F0dGVyIiwKICAgICAgICAgICAgICAgIGhjYWVzKHggPSAiY2FyYXQiLCB5ID0gInByaWNlIiwgc2l6ZSA9ICJkZXB0aCIsIGdyb3VwID0gImN1dCIpKSAlPiUKICBoY19hZGRfc2VyaWVzKGZpdCwgdHlwZSA9ICJsaW5lIiwgaGNhZXMoeCA9ICJjYXJhdCIsIHkgPSAiLmZpdHRlZCIpLAogICAgICAgICAgICAgICAgbmFtZSA9ICJGaXQiLCBpZCA9ICJmaXQiKSAlPiUKICBoY19hZGRfc2VyaWVzKGZpdCwgdHlwZSA9ICJhcmVhcmFuZ2UiLAogICAgICAgICAgICAgICAgaGNhZXMoeCA9ICJjYXJhdCIsIGxvdyA9ICIuZml0dGVkIC0gMiouc2UuZml0IiwKICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiLmZpdHRlZCArIDIqLnNlLmZpdCIpLAogICAgICAgICAgICAgICAgbGlua2VkVG8gPSAiZml0IikKCgpgYGAKCgoKCmBgYHtyfQpoaWdoY2hhcnQoKSAlPiUKICBoY19jaGFydCh0eXBlID0gImFyZWEiKSAlPiUKICBoY190aXRsZSh0ZXh0ID0gIkhpc3RvcmljIGFuZCBFc3RpbWF0ZWQgV29ybGR3aWRlIFBvcHVsYXRpb24gRGlzdHJpYnV0aW9uIGJ5IFJlZ2lvbiIpICU+JQogIGhjX3N1YnRpdGxlKHRleHQgPSAiU291cmNlOiBXaWtpcGVkaWEub3JnIikgJT4lCiAgaGNfeEF4aXMoY2F0ZWdvcmllcyA9IGMoIjE3NTAiLCAiMTgwMCIsICIxODUwIiwgIjE5MDAiLCAiMTk1MCIsICIxOTk5IiwgIjIwNTAiKSwKICAgICAgICAgICB0aWNrbWFya1BsYWNlbWVudCA9ICJvbiIsCiAgICAgICAgICAgdGl0bGUgPSBsaXN0KGVuYWJsZWQgPSBGQUxTRSkpICU+JQogIGhjX3lBeGlzKHRpdGxlID0gbGlzdCh0ZXh0ID0gIlBlcmNlbnQiKSkgJT4lCiAgaGNfdG9vbHRpcChwb2ludEZvcm1hdCA9ICI8c3BhbiBzdHlsZT1cImNvbG9yOntzZXJpZXMuY29sb3J9XCI+e3Nlcmllcy5uYW1lfTwvc3Bhbj46CiAgICAgICAgICAgICA8Yj57cG9pbnQucGVyY2VudGFnZTouMWZ9JTwvYj4gKHtwb2ludC55OiwuMGZ9IG1pbGxpb25zKTxici8+IiwKICAgICAgICAgICAgIHNoYXJlZCA9IFRSVUUpICU+JQogIGhjX3Bsb3RPcHRpb25zKGFyZWEgPSBsaXN0KAogICAgIHN0YWNraW5nID0gInBlcmNlbnQiLAogICAgIGxpbmVDb2xvciA9ICIjZmZmZmZmIiwKICAgICBsaW5lV2lkdGggPSAxLAogICAgIG1hcmtlciA9IGxpc3QoCiAgICAgICBsaW5lV2lkdGggPSAxLAogICAgICAgbGluZUNvbG9yID0gIiNmZmZmZmYiCiAgICAgICApKQogICAgICkgJT4lCiAgaGNfYWRkX3NlcmllcyhuYW1lID0gIkFzaWEiLCBkYXRhID0gYyg1MDIsIDYzNSwgODA5LCA5NDcsIDE0MDIsIDM2MzQsIDUyNjgpKSAlPiUKICBoY19hZGRfc2VyaWVzKG5hbWUgPSAiQWZyaWNhIiwgZGF0YSA9IGMoMTA2LCAxMDcsIDExMSwgMTMzLCAyMjEsIDc2NywgMTc2NikpICU+JQogIGhjX2FkZF9zZXJpZXMobmFtZSA9ICJFdXJvcGUiLCBkYXRhID0gYygxNjMsIDIwMywgMjc2LCA0MDgsIDU0NywgNzI5LCA2MjgpKSAlPiUKICBoY19hZGRfc2VyaWVzKG5hbWUgPSAiQW1lcmljYSIsIGRhdGEgPSBjKDE4LCAzMSwgNTQsIDE1NiwgMzM5LCA4MTgsIDEyMDEpKSAlPiUKICBoY19hZGRfc2VyaWVzKG5hbWUgPSAiT2NlYW5pYSIsIGRhdGEgPSBjKDIsIDIsIDIsIDYsIDEzLCAzMCwgNDYpKQpgYGAKCgoKCmBgYHtyfQp4IDwtIHF1YW50bW9kOjpnZXRTeW1ib2xzKCJHT09HIiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKCmhjaGFydCh4KQpgYGAKCgoKCmBgYHtyfQp5IDwtIHF1YW50bW9kOjpnZXRTeW1ib2xzKCJBTVpOIiwgYXV0by5hc3NpZ24gPSBGQUxTRSkKCmhpZ2hjaGFydCh0eXBlID0gInN0b2NrIikgJT4lCiAgaGNfYWRkX3Nlcmllcyh4KSAlPiUKICBoY19hZGRfc2VyaWVzKHksIHR5cGUgPSAib2hsYyIpCmBgYAoKSGlnaG1hcHMgLSBNYXAgQ29sbGVjdGlvbiAgCmh0dHBzOi8vY29kZS5oaWdoY2hhcnRzLmNvbS9tYXBkYXRhLyAgCgoKCmBgYHtyfQpoY21hcCgiaHR0cHM6Ly9jb2RlLmhpZ2hjaGFydHMuY29tL21hcGRhdGEvY291bnRyaWVzL2luL2luLWFsbC5qcyIpJT4lCiAgaGNfdGl0bGUodGV4dCA9ICJJbmRpYSIpCmBgYAoKCgpgYGB7cn0KaGNtYXAoImh0dHBzOi8vY29kZS5oaWdoY2hhcnRzLmNvbS9tYXBkYXRhL2NvdW50cmllcy90ci90ci1hbGwuanMiKSU+JQogIGhjX3RpdGxlKHRleHQgPSAiVHVya2V5IikKYGBgCgpgYGAKZG93bmxvYWRfbWFwX2RhdGE6IERvd25sb2FkIHRoZSBnZW9qc29uIGRhdGEgZnJvbSB0aGUgaGlnaGNoYXJ0cyBjb2xsZWN0aW9uLgpnZXRfZGF0YV9mcm9tX21hcDogR2V0IHRoZSBwcm9wZXJ0aWVzIGZvciBlYWNoIHJlZ2lvbiBpbiB0aGUgbWFwLCBhcyB0aGUga2V5cyBmcm9tIHRoZSBtYXAgZGF0YS4KYGBgCgoKCmBgYHtyfQptYXBkYXRhIDwtIGdldF9kYXRhX2Zyb21fbWFwKGRvd25sb2FkX21hcF9kYXRhKCJodHRwczovL2NvZGUuaGlnaGNoYXJ0cy5jb20vbWFwZGF0YS9jb3VudHJpZXMvaW4vaW4tYWxsLmpzIikpCmdsaW1wc2UobWFwZGF0YSkKYGBgCgoKCgpgYGB7cn0KCiNwb3B1bGF0aW9uIHN0YXRlIHdpc2UKcG9wIDwtICBhcy5kYXRhLmZyYW1lKGMoODQ2NzM1NTYsIDEzODI2MTEsIDMxMTY5MjcyLCAxMDM4MDQ2MzcsIDEwNTU0NTAsIDI1NTQwMTk2LCAzNDI4NTMsIDI0MjkxMSwgMTg5ODAwMDAsIDE0NTc3MjMsIDYwMzgzNjI4LCAyNTM1MzA4MSwgNjg2NDYwMiwKMTI1NDg5MjYsIDMyOTY2MjM4LCA2MTEzMDcwNCwgMzMzODc2NzcsIDY0NDI5LCA3MjU5NzU2NSwgMTEyMzcyOTcyLCAyNzIxNzU2LCAyOTY0MDA3LCAxMDkxMDE0LCAxOTgwNjAyLCA0MTk0NzM1OCwgMTI0NDQ2NCwKMjc3MDQyMzYsIDY4NjIxMDEyLCA2MDc2ODgsIDcyMTM4OTU4LCAzNjcxMDMyLCAyMDcyODE0NzcsIDEwMTE2NzUyLDkxMzQ3NzM2KSkKCnN0YXRlIDwtICBtYXBkYXRhJT4lCiAgc2VsZWN0KGBoYy1hMmApJT4lCiAgYXJyYW5nZShgaGMtYTJgKQoKU3RhdGVfcG9wIDwtICBhcy5kYXRhLmZyYW1lKGMoc3RhdGUsIHBvcCkpCm5hbWVzKFN0YXRlX3BvcCk9IGMoIlN0YXRlIiwgIlBvcHVsYXRpb24iKQoKaGNtYXAoImh0dHBzOi8vY29kZS5oaWdoY2hhcnRzLmNvbS9tYXBkYXRhL2NvdW50cmllcy9pbi9pbi1hbGwuanMiLCBkYXRhID0gU3RhdGVfcG9wLCB2YWx1ZSA9ICJQb3B1bGF0aW9uIiwKICAgICAgam9pbkJ5ID0gYygiaGMtYTIiLCAiU3RhdGUiKSwgbmFtZSA9ICJGYWtlIGRhdGEiLAogICAgICBkYXRhTGFiZWxzID0gbGlzdChlbmFibGVkID0gVFJVRSwgZm9ybWF0ID0gJ3twb2ludC5uYW1lfScpLAogICAgICBib3JkZXJDb2xvciA9ICIjRkFGQUZBIiwgYm9yZGVyV2lkdGggPSAwLjEsCiAgICAgIHRvb2x0aXAgPSBsaXN0KHZhbHVlRGVjaW1hbHMgPSAwKSkKCmBgYAoKCgoKYGBge3J9CmRhdGEobXBnLCBwYWNrYWdlID0gImdncGxvdDIiKQoKbXBnZyA8LSBtcGcgJT4lCiAgZmlsdGVyKGNsYXNzICVpbiUgYygic3V2IiwgImNvbXBhY3QiLCAibWlkc2l6ZSIpKSAlPiUKICBncm91cF9ieShjbGFzcywgbWFudWZhY3R1cmVyKSAlPiUKICBzdW1tYXJpemUoY291bnQgPSBuKCkpCgpjYXRlZ29yaWVzX2dyb3VwZWQgPC0gbXBnZyAlPiUKICBncm91cF9ieShuYW1lID0gY2xhc3MpICU+JQogIGRvKGNhdGVnb3JpZXMgPSAuJG1hbnVmYWN0dXJlcikgJT4lCiAgbGlzdF9wYXJzZSgpCgpoaWdoY2hhcnQoKSAlPiUKICBoY194QXhpcyhjYXRlZ29yaWVzID0gY2F0ZWdvcmllc19ncm91cGVkKSAlPiUKICBoY19hZGRfc2VyaWVzKGRhdGEgPSBtcGdnLCB0eXBlID0gImJhciIsIGhjYWVzKHkgPSAiY291bnQiLCBjb2xvciA9ICJtYW51ZmFjdHVyZXIiKSwKICAgICAgICAgICAgICAgIHNob3dJbkxlZ2VuZCA9IEZBTFNFKQpgYGAKCgoKCgoKCgpgYGB7cn0KZGYgPC0gZGF0YV9mcmFtZSgKICBuYW1lID0gYygiQW5pbWFscyIsICJGcnVpdHMiLCAiQ2FycyIpLAogIHkgPSBjKDUsIDIsIDQpLAogIGRyaWxsZG93biA9IHRvbG93ZXIobmFtZSkKKQoKCmRzIDwtIGxpc3RfcGFyc2UoZGYpCm5hbWVzKGRzKSA8LSBOVUxMCgoKaGMgPC0gaGlnaGNoYXJ0KCkgJT4lCiAgaGNfY2hhcnQodHlwZSA9ICJjb2x1bW4iKSAlPiUKICBoY190aXRsZSh0ZXh0ID0gIkJhc2ljIGRyaWxsZG93biIpICU+JQogIGhjX3hBeGlzKHR5cGUgPSAiY2F0ZWdvcnkiKSAlPiUKICBoY19sZWdlbmQoZW5hYmxlZCA9IEZBTFNFKSAlPiUKICBoY19wbG90T3B0aW9ucygKICAgIHNlcmllcyA9IGxpc3QoCiAgICAgIGJvZGVyV2lkdGggPSAwLAogICAgICBkYXRhTGFiZWxzID0gbGlzdChlbmFibGVkID0gVFJVRSkKICAgICkKICApICU+JQogIGhjX2FkZF9zZXJpZXMoCiAgICBuYW1lID0gIlRoaW5ncyIsCiAgICBjb2xvckJ5UG9pbnQgPSBUUlVFLAogICAgZGF0YSA9IGRzCiAgKQoKZGZhbiA8LSBkYXRhX2ZyYW1lKAogIG5hbWUgPSBjKCJDYXRzIiwgIkRvZ3MiLCAiQ293cyIsICJTaGVlcCIsICJQaWdzIiksCiAgdmFsdWUgPSBjKDQsIDMsIDEsIDIsIDEpCikKCmRmZnJ1IDwtIGRhdGFfZnJhbWUoCiAgbmFtZSA9IGMoIkFwcGxlIiwgIk9yZ2FuZXMiKSwKICB2YWx1ZSA9IGMoNCwgMikKKQoKZGZjYXIgPC0gZGF0YV9mcmFtZSgKICBuYW1lID0gYygiVG95b3RhIiwgIk9wZWwiLCAiVm9sa3N3YWdlIiksCiAgdmFsdWUgPSBjKDQsIDIsIDIpCikKCnNlY29uZF9lbF90b19udW1lcmljIDwtIGZ1bmN0aW9uKGxzKXsKCiAgbWFwKGxzLCBmdW5jdGlvbih4KXsKICAgIHhbWzJdXSA8LSBhcy5udW1lcmljKHhbWzJdXSkKICAgIHgKICB9KQoKfQoKZHNhbiA8LSBzZWNvbmRfZWxfdG9fbnVtZXJpYyhsaXN0X3BhcnNlMihkZmFuKSkKCmRzZnJ1IDwtIHNlY29uZF9lbF90b19udW1lcmljKGxpc3RfcGFyc2UyKGRmZnJ1KSkKCmRzY2FyIDwtIHNlY29uZF9lbF90b19udW1lcmljKGxpc3RfcGFyc2UyKGRmY2FyKSkKCmhjICU+JQogIGhjX2RyaWxsZG93bigKICAgIGFsbG93UG9pbnREcmlsbGRvd24gPSBUUlVFLAogICAgc2VyaWVzID0gbGlzdCgKICAgICAgbGlzdCgKICAgICAgICBpZCA9ICJhbmltYWxzIiwKICAgICAgICBkYXRhID0gZHNhbgogICAgICApLAogICAgICBsaXN0KAogICAgICAgIGlkID0gImZydWl0cyIsCiAgICAgICAgZGF0YSA9IGRzZnJ1CiAgICAgICksCiAgICAgIGxpc3QoCiAgICAgICAgaWQgPSAiY2FycyIsCiAgICAgICAgZGF0YSA9IGRzY2FyCiAgICAgICkKICAgICkKICApCgpgYGAKCgoKCgoKYGBge3J9CnRtIDwtIHBva2Vtb24gJT4lCiAgbXV0YXRlKHR5cGVfMiA9IGlmZWxzZShpcy5uYSh0eXBlXzIpLCBwYXN0ZSgib25seSIsIHR5cGVfMSksIHR5cGVfMiksCiAgICAgICAgIHR5cGVfMSA9IHR5cGVfMSkgJT4lCiAgZ3JvdXBfYnkodHlwZV8xLCB0eXBlXzIpICU+JQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgdHJlZW1hcDo6dHJlZW1hcChpbmRleCA9IGMoInR5cGVfMSIsICJ0eXBlXzIiKSwKICAgICAgICAgICAgICAgICAgIHZTaXplID0gIm4iLCB2Q29sb3IgPSAidHlwZV8xIikKCnRtJHRtIDwtIHRtJHRtICU+JQogIHRibF9kZigpICU+JQogIGxlZnRfam9pbihwb2tlbW9uICU+JSBzZWxlY3QodHlwZV8xLCB0eXBlXzIsIGNvbG9yX2YpICU+JSBkaXN0aW5jdCgpLCBieSA9IGMoInR5cGVfMSIsICJ0eXBlXzIiKSkgJT4lCiAgbGVmdF9qb2luKHBva2Vtb24gJT4lIHNlbGVjdCh0eXBlXzEsIGNvbG9yXzEpICU+JSBkaXN0aW5jdCgpLCBieSA9IGMoInR5cGVfMSIpKSAlPiUKICBtdXRhdGUodHlwZV8xID0gcGFzdGUwKCJNYWluICIsIHR5cGVfMSksCiAgICAgICAgIGNvbG9yID0gaWZlbHNlKGlzLm5hKGNvbG9yX2YpLCBjb2xvcl8xLCBjb2xvcl9mKSkKCmhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXNfdHJlZW1hcCh0bSwgYWxsb3dEcmlsbFRvTm9kZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dEFsZ29yaXRobSA9ICJzcXVhcmlmaWVkIikKYGBgCgoKCmBgYHtyfQpwb2tlbW9uJT4lCiAgY291bnQodHlwZV8xKSU+JQogIGFycmFuZ2UobiklPiUKICBoY2hhcnQodHlwZSA9ICJiYXIiLCBoY2Flcyh4ID0gInR5cGVfMSIsIHkgPSAibiIsIGNvbG9yID0gInR5cGVfMSIpKSU+JQogIGhjX2V4cG9ydGluZyhlbmFibGVkID0gVFJVRSkKYGBgCgoKCgpgYGB7cn0KcG9rZW1vbiU+JQogIGNvdW50KHR5cGVfMSklPiUKICBhcnJhbmdlKG4pJT4lCiAgaGNoYXJ0KHR5cGUgPSAiYmFyIiwgaGNhZXMoeCA9ICJ0eXBlXzEiLCB5ID0gIm4iLCBjb2xvciA9ICJ0eXBlXzEiKSklPiUKICBoY19leHBvcnRpbmcoZW5hYmxlZCA9IFRSVUUpJT4lCmhjX2FkZF90aGVtZShoY190aGVtZV9jaGFsaygpKQpgYGAKCgoKCgoKYGBge3J9CmRhdGEoIndlYXRoZXIiKQoKeCA8LSBjKCJNaW4iLCAiTWVhbiIsICJNYXgiKQp5IDwtIHNwcmludGYoIntwb2ludC4lc30iLCBjKCJtaW5fdGVtcGVyYXR1cmVjIiwgIm1lYW5fdGVtcGVyYXR1cmVjIiwgIm1heF90ZW1wZXJhdHVyZWMiKSkKdGx0aXAgPC0gdG9vbHRpcF90YWJsZSh4LCB5KQoKaGNoYXJ0KHdlYXRoZXIsIHR5cGUgPSAiY29sdW1ucmFuZ2UiLAogICAgICAgaGNhZXMoeCA9ICJkYXRlIiwgbG93ID0gIm1pbl90ZW1wZXJhdHVyZWMiLCBoaWdoID0gIm1heF90ZW1wZXJhdHVyZWMiLAogICAgICAgICAgICAgY29sb3IgPSAibWVhbl90ZW1wZXJhdHVyZWMiKSkgJT4lCiAgaGNfY2hhcnQocG9sYXIgPSBUUlVFKSAlPiUKICBoY195QXhpcyggbWF4ID0gMzAsIG1pbiA9IC0xMCwgbGFiZWxzID0gbGlzdChmb3JtYXQgPSAie3ZhbHVlfSBDIiksCiAgICAgICAgICAgIHNob3dGaXJzdExhYmVsID0gRkFMU0UpICU+JQogIGhjX3hBeGlzKAogICAgdGl0bGUgPSBsaXN0KHRleHQgPSAiIiksIGdyaWRMaW5lV2lkdGggPSAwLjUsCiAgICBsYWJlbHMgPSBsaXN0KGZvcm1hdCA9ICJ7dmFsdWU6ICVifSIpKSAlPiUKICBoY190b29sdGlwKHVzZUhUTUwgPSBUUlVFLCBwb2ludEZvcm1hdCA9IHRsdGlwLAogICAgICAgICAgICAgaGVhZGVyRm9ybWF0ID0gYXMuY2hhcmFjdGVyKHRhZ3Mkc21hbGwoIntwb2ludC54OiVkICVCLCAlWX0iKSkpCgpgYGAKCgoKLS0tCgoKIyB0YXVjaGFydHMKCgpodHRwczovL3d3dy5pbmZvd29ybGQuY29tL3ZpZGVvLzg3MzM3L3ItdGlwLWhvdy10by1jcmVhdGUtZWFzeS1pbnRlcmFjdGl2ZS1zY2F0dGVyLXBsb3RzLXdpdGgtdGF1Y2hhcnRzCgoKLS0tCiAgCjxpZnJhbWUgc3JjPSIvL2NvbnRlbnQuandwbGF0Zm9ybS5jb20vcGxheWVycy9Ha2JScDhuNy1CSXJuOXVzWS5odG1sIiB3aWR0aD0iNjQwIiBoZWlnaHQ9IjM2MCIgZnJhbWVib3JkZXI9IjAiIHNjcm9sbGluZz0iYXV0byI+PC9pZnJhbWU+ICAKCi0tLQoKCgoKYGBge3J9CmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiaHJicm1zdHIvdGF1Y2hhcnRzIikKIyBnaXRodWJpbnN0YWxsOjpnaXRodWJpbnN0YWxsKCJ0YXVjaGFydHMiKQpgYGAKCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGF1Y2hhcnRzKQpkYXRhKCJtdGNhcnMiKQpgYGAKCgpgYGB7cn0KbXRjYXJzMiA8LSBtdGNhcnMgJT4lIAogIHNlbGVjdCh3dCwgbXBnKSAlPiUgCiAgbXV0YXRlKG1vZGVsID0gcm93Lm5hbWVzKG10Y2FycykpCmBgYAoKCmBgYHtyfQp0YXVjaGFydHM6OnRhdWNoYXJ0KG10Y2FyczIpICU+JSAKICB0YXVfcG9pbnQoeCA9ICJ3dCIsIHkgPSAibXBnIikgJT4lIAogIHRhdV90b29sdGlwKCkgJT4lIAogIHRhdV90cmVuZGxpbmUoKQpgYGAKCgojIGdnYW5pbWF0ZQoKaHR0cHM6Ly93d3cuaW5mb3dvcmxkLmNvbS92aWRlby84OTk4Ny9yLXRpcC1hbmltYXRpb25zLWluLXIKCgojIGdncGxvdDIKCgpodHRwOi8vci1zdGF0aXN0aWNzLmNvL2dncGxvdDItVHV0b3JpYWwtV2l0aC1SLmh0bWwKCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpkaWFtb25kcwpnZ3Bsb3QoZGlhbW9uZHMpICAjIGlmIG9ubHkgdGhlIGRhdGFzZXQgaXMga25vd24uCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4PWNhcmF0KSkgICMgaWYgb25seSBYLWF4aXMgaXMga25vd24uIFRoZSBZLWF4aXMgY2FuIGJlIHNwZWNpZmllZCBpbiByZXNwZWN0aXZlIGdlb21zLgpgYGAKCgpgYGB7cn0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeD1jYXJhdCwgeT1wcmljZSkpICAjIGlmIGJvdGggWCBhbmQgWSBheGVzIGFyZSBmaXhlZCBmb3IgYWxsIGxheWVycy4KYGBgCgoKYGBge3J9CmdncGxvdChkaWFtb25kcywgYWVzKHg9Y2FyYXQsIGNvbG9yPWN1dCkpICAjIEVhY2ggY2F0ZWdvcnkgb2YgdGhlICdjdXQnIHZhcmlhYmxlIHdpbGwgbm93IGhhdmUgYSBkaXN0aW5jdCAgY29sb3IsIG9uY2UgYSBnZW9tIGlzIGFkZGVkLgpgYGAKCgpgYGB7cn0KZ2dwbG90KGRpYW1vbmRzLCBhZXMoeD1jYXJhdCksIGNvbG9yPSJzdGVlbGJsdWUiKQpgYGAKCgoKLSBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvCgoKYGBge3J9CmdncGxvdChkaWFtb25kcywgYWVzKHg9Y2FyYXQsIHk9cHJpY2UsIGNvbG9yPWN1dCkpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9zbW9vdGgoKQojIEFkZGluZyBzY2F0dGVycGxvdCBnZW9tIChsYXllcjEpIGFuZCBzbW9vdGhpbmcgZ2VvbSAobGF5ZXIyKS4KYGBgCgoKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMpICsgCiAgZ2VvbV9wb2ludChhZXMoeD1jYXJhdCwgeT1wcmljZSwgY29sb3I9Y3V0KSkgKyAKICBnZW9tX3Ntb290aChhZXMoeD1jYXJhdCwgeT1wcmljZSwgY29sb3I9Y3V0KSkKIyBTYW1lIGFzIGFib3ZlIGJ1dCBzcGVjaWZ5aW5nIHRoZSBhZXN0aGV0aWNzIGluc2lkZSB0aGUgZ2VvbXMuCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdChkaWFtb25kcykgKyAKICBnZW9tX3BvaW50KGFlcyh4PWNhcmF0LCB5PXByaWNlLCBjb2xvcj1jdXQpKSArIAogIGdlb21fc21vb3RoKGFlcyh4PWNhcmF0LCB5PXByaWNlKSkgIyBSZW1vdmUgY29sb3IgZnJvbSBnZW9tX3Ntb290aApnZ3Bsb3QoZGlhbW9uZHMsIGFlcyh4PWNhcmF0LCB5PXByaWNlKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1jdXQpKSArIAogIGdlb21fc21vb3RoKCkgICMgc2FtZSBidXQgc2ltcGxlcgpgYGAKCgpjb250aW51ZSBmcm9tIGhlcmUKaHR0cDovL3Itc3RhdGlzdGljcy5jby9nZ3Bsb3QyLVR1dG9yaWFsLVdpdGgtUi5odG1sCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg==